/*
 * A RMISpellingServer for check, add ,remove the wordlist.
 * Written by YUE CHI
 */

import java.io.IOException;
import java.net.SocketException;
import java.rmi.AlreadyBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

/**
 * A RMISpellingServer for check, add ,remove the wordlist.
 * @author YUE CHI
 * @version 1.0
 */
public class RMISpellingServer
{

  /**
   * The minimum valid port number.
   */
  public static final int MIN_PORT_NUMBER = 1024;

  /**
   * The length of the input string from the commandline.
   */
  public static final int INPUT_LENGHTH = 3;
  
  /**
   * The maximum valid port number.
   */
  public static final int MAX_PORT_NUMBER = 65535;
 
  /**
   * The Remotespelling to be extended. Shoud be static because it is essential
   * that the object you export remain in scope after you bind it to the RMI
   * registry.
   */
  private static RemoteSpelling my_remotespelling;

  /**
   * The port number.
   */
  private final int my_port;

  /**
   * The service name.
   */
  private final String my_servicename;

  /**
   * The registry.
   */
  private final Registry my_registry;

  /**
   * The constructor of RMISpellingServer.
   * 
   * @param the_args the input string array from commandline.
   * @throws SocketException socket problem
   */
  public RMISpellingServer(final String[] the_args) throws SocketException
  {
    if (the_args.length != INPUT_LENGHTH)
    {
      System.err.println("Usage: java RMISpellingServer <port> <service-name> <word-list>");
      System.exit(1);
    }
    this.my_port = getPort(the_args);
    this.my_servicename = getservicename(the_args);
    this.my_registry = getregistry(my_port);
    this.my_remotespelling = my_remotespelling;
  }

  /**
   * Get the port number.
   * 
   * @param the_args the input string
   * @return the port number
   */
  private int getPort(final String[] the_args)
  {
    int iport = 0;
    try
    {
      iport = Integer.parseInt(the_args[0]);
      Log.out("Successful get the port number.");
    }
    catch (final NumberFormatException e)
    {
      System.err.println("Port number must be numeric");
      System.exit(1);
    }
    if (iport < MIN_PORT_NUMBER || iport > MAX_PORT_NUMBER)
    {
      System.err.println("Port number must be between " + MIN_PORT_NUMBER + " and " +
                         MAX_PORT_NUMBER + " inclusive.");
      System.exit(1);
    }
    return iport;
  }

  /**
   * Get the servicename for registration for the server.
   * 
   * @param the_args the input string array
   * @return the service name get.
   */
  private String getservicename(final String[] the_args)
  {
    String temp = null;
    try
    {
      temp = the_args[1];
      Log.out("Successfully get the service name.");

    }
    catch (final NumberFormatException e)
    {
      System.err.println("Cannot get the service name. " + e);
    }
    return temp;
  }

  /**
   * Get the registry for the RMI server.
   * 
   * @param the_port the port to regist.
   * @return the registry param
   */
  private Registry getregistry(final int the_port)
  {
    Registry temp = null;
    try
    {
      temp = LocateRegistry.createRegistry(the_port);
      Log.out("Successfully registered as name " + temp.getClass().getName());

    }
    catch (final RemoteException e)
    {
      System.err.println("Cannot export the service.");
      e.printStackTrace();
    }
    return temp;
  }

  /**
   * To Run the RMI server. The server will stop after 2 hours.
   * 
   * @param the_args the input string from command line.
   * @throws SocketException socket problems
   */
  public static void main(final String[] the_args) throws SocketException
  {
    final RMISpellingServer server = new RMISpellingServer(the_args);
    try
    {
      server.my_remotespelling = new UnicastRemoteSpelling(the_args[2]);
      // pass 0 to exportObject so that it will choose a random port
      final Object temp =
          UnicastRemoteObject.exportObject(server.my_remotespelling, 0);
      server.my_registry.bind(server.my_servicename, (Remote) temp);
      Log.out("Successfully exported spelling service as " + server.my_servicename +
              " on port " + server.my_port);
    }
    catch (final RemoteException e)
    {
      System.err.println("Problem exporting the service.");
      e.printStackTrace();
    }
    catch (final IOException e)
    {
      System.err.println("Problem loading word list.");
      e.printStackTrace();
    }
    catch (final AlreadyBoundException e)
    {
      System.err.println("Service has already bound");
      e.printStackTrace();
    }

  }

}
